/**
 * <one line to give the program's name and a brief idea of what it does.>
 * Copyright (C) 2010 Sean Beecroft
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * @version 1.10 2010-01-01
 * @author Sean Beecroft
 */
package yawiki.client.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JInternalFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTree;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

import yawiki.client.application.YGlobals;
import yawiki.client.browser.YBrowser;
import yawiki.client.editors.YCodeEditor;
import yawiki.client.editors.YDesignEditor;

public class YEditorMainFrame extends JInternalFrame {

    private static int openFrameCount = 0;
    private static final int xOffset = 30, yOffset = 30;
    private InputStream inputStream = null;
    private JTree tree = null;
    private UndoManager undo = new UndoManager();
    private UndoableEditListener undoHandler = new UndoHandler();
    private UndoAction undoAction = new UndoAction();
    private RedoAction redoAction = new RedoAction();
    private SaveAction SaveAction = new SaveAction();
    private YCodeEditor textPane = null;

    public void dispose() {
        super.dispose();
        System.out.println("...");
        openFrameCount--;
    }

    class UndoHandler implements UndoableEditListener {

        /**
         * Messaged when the Document has created an edit, the edit is added to
         * <code>undo</code>, an instance of UndoManager.
         */
        public void undoableEditHappened(UndoableEditEvent e) {
            undo.addEdit(e.getEdit());
            undoAction.update();
            redoAction.update();
        }
    }

    class SaveAction extends AbstractAction {

        public SaveAction() {
            super("Save");
            setEnabled(false);
        }

        public void actionPerformed(ActionEvent e) {
            try {
                JOptionPane.showConfirmDialog(null, "Save is temporarily disabled for testing");
            } catch (CannotUndoException ex) {
                System.out.println("Unable to undo: " + ex);
                ex.printStackTrace();
            }
        }

        protected void update() {
        }
    }

    class UndoAction extends AbstractAction {

        public UndoAction() {
            super("Undo");
            setEnabled(false);
        }

        public void actionPerformed(ActionEvent e) {
            try {
                undo.undo();
            } catch (CannotUndoException ex) {
                System.out.println("Unable to undo: " + ex);
                ex.printStackTrace();
            }
            update();
            redoAction.update();
        }

        protected void update() {
            if (undo.canUndo()) {
                setEnabled(true);
                putValue(Action.NAME, undo.getUndoPresentationName());
            } else {
                setEnabled(false);
                putValue(Action.NAME, "Undo");
            }
        }
    }

    class RedoAction extends AbstractAction {

        public RedoAction() {
            super("Redo");
            setEnabled(false);
        }

        public void actionPerformed(ActionEvent e) {
            try {
                undo.redo();
            } catch (CannotRedoException ex) {
                System.out.println("Unable to redo: " + ex);
                ex.printStackTrace();
            }
            update();
            undoAction.update();
        }

        protected void update() {
            if (undo.canRedo()) {
                setEnabled(true);
                putValue(Action.NAME, undo.getRedoPresentationName());
            } else {
                setEnabled(false);
                putValue(Action.NAME, "Redo");
            }
        }
    }

    public YEditorMainFrame(final String title) {
        super("Document - " + title, true, true, true, true);
        try {
            setResizable(true);
            openFrameCount++;
            setPreferredSize(new Dimension(700, 500));
            setLocation(xOffset * openFrameCount, yOffset * openFrameCount);

            String stitle = title;
            stitle = stitle.replaceAll("'", "&apos;");
            stitle = stitle.replaceAll(" ", "_");


            URL url = new URL("http://" + YGlobals.domain + YGlobals.context + "pump?page=" + stitle);

            if (!YBrowser.exists(url.toString())) {
                JOptionPane.showMessageDialog(null, "Page specified does not exist.");
            }

            InputStream is = url.openStream();

            java.io.InputStreamReader inputStreamReader = new java.io.InputStreamReader(is, "UTF8");
            final java.io.BufferedReader bufferedReader = new java.io.BufferedReader(inputStreamReader);


            inputStream = is;
            // this is all temp..
            String S = "";
            int n = 0;
            StringBuffer buf = new StringBuffer("");

            while ((S = bufferedReader.readLine()) != null) {
                try {
                    buf.append(S);
                    buf.append("\n");
                } catch (Exception ex) {
                    System.out.println(ex);
                }
            }

            textPane = new YCodeEditor(undo);

            textPane.setText(buf.toString());
            JScrollPane textPaneSp = new JScrollPane(textPane,
                    ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                    ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
            YLineNumber lineNumber = new YLineNumber(textPane);

            YDesignEditor htmlDocumentEditor = new YDesignEditor();

            textPane.setCaretPosition(0);
            textPaneSp.setRowHeaderView(lineNumber);
            textPane.getDocument().addUndoableEditListener(undoHandler);
            getContentPane().setLayout(new BorderLayout());
            JPanel toolbar = new JPanel();
            toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
            JButton button1 = new JButton("Save");
            JButton button2 = new JButton("Preview");

            final YBrowser previewSp = new YBrowser();
            button1.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    boolean b = true;
                    if (b) {
                        save(title);
                        previewSp.setPage("http://" + YGlobals.domain + YGlobals.context + title);
                    } else {
                        JOptionPane.showConfirmDialog(null, "Save is temporarily disabled for testing");

                    }
                }
            });
            JTabbedPane tabbedPane = new JTabbedPane();

            tabbedPane.add(textPaneSp, "Code");
            tabbedPane.add(htmlDocumentEditor, "Design");
            tabbedPane.add(previewSp, "Preview");


            getContentPane().add(toolbar, BorderLayout.NORTH);
            getContentPane().add(tabbedPane, BorderLayout.CENTER);
            setVisible(true);
            pack();

            try {
                setSelected(true);
            } catch (java.beans.PropertyVetoException e) {
            }
        } catch (IOException ex) {
            System.out.println("IOException:" + ex);
        } catch (Exception ex) {
            System.out.println("XMLEditor()" + ex);
        }
    }

    public void save(String title) {
        String text = textPane.getText();

        StringBuffer buf = new StringBuffer(text);
        try {
            // Construct data
            String kc = ""; // get kc from server.
            String data = "keycode=" + kc + "&page=" + URLEncoder.encode(title, "UTF-8") + "&buf=" + URLEncoder.encode(buf.toString(), "UTF-8");

            // Send data
            URL url = new URL("http://" + YGlobals.domain + YGlobals.context + "save");
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream(), "UTF8");
            wr.write(data);
            wr.flush();

            // Get the response
            BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            String message = "";
            while ((line = rd.readLine()) != null) {
                // Process line...
                message = message + line;

            }
            if (message.equals("")) {
                JOptionPane.showMessageDialog(null, "Saved OK");

            } else {
                JOptionPane.showMessageDialog(null, message);
            }
            wr.close();
            rd.close();
        } catch (Exception e) {
        }
    }
}
